package com.doyoulike.service.gen;

import cn.hutool.core.util.StrUtil;
import com.doyoulike.config.CusException;
import com.doyoulike.config.gen.GenConfig;
import com.doyoulike.config.gen.GenTemplate;
import com.doyoulike.entity.GenTable;
import com.doyoulike.enums.GenTypeEnum;
import com.doyoulike.service.template.ITemplateEngineService;
import com.doyoulike.util.FileTool;
import com.doyoulike.util.LoadTemplateTool;
import com.doyoulike.vo.out.GenData;
import com.doyoulike.vo.out.GeneratedContent;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成服务
 */
@Service
public class CodeGenService {

    @Autowired
    private GenConfig genConfig;

    @Resource(name = "freeMarkersService")
    private ITemplateEngineService freeMarkersService;

    /**
     * 预览
     */
    public List<GeneratedContent> preview(GenTable genTable) {
        // 一、组装生成数据
        GenData genData = GenVOBuild.build(genTable);

        // 二、根据路径加载模板
        List<GenTemplate> templates = loadTemplateList(genTable.getGenTypeCode());

        // 2.1 过滤出主表模板
        List<GenTemplate> mainTemplates = templates.stream().filter(s -> !s.getChild()).collect(Collectors.toList());

        // 2.2 过滤出子表模板
        List<GenTemplate> childTemplates = templates.stream().filter(GenTemplate::getChild).collect(Collectors.toList());

        // 三、从模板中解析出文件内容
        List<GeneratedContent> result = resolveTemplateContent(genData, mainTemplates, childTemplates);

        // 四、返回内容
        return result;
    }

    /**
     * 生成代码
     *
     * 一、组装数据
     *
     * 二、获取模板（从 XML 中获取模板）
     *
     * 三、解析模板内容（使用模板引擎解析模板内容）
     *
     * 四、根据内容创建文件
     *
     */
    public void generatorCode(GenTable genTable) {
        // 一、组装生成数据
        GenData genData = GenVOBuild.build(genTable);

        // 二、加载模板
        List<GenTemplate> templates = loadTemplateList(genTable.getGenTypeCode());

        // 2.1 过滤出主表模板
        List<GenTemplate> mainTemplates = templates.stream().filter(s -> !s.getChild()).collect(Collectors.toList());

        // 2.2 过滤出子表模板
        List<GenTemplate> childTemplates = templates.stream().filter(GenTemplate::getChild).collect(Collectors.toList());

        // 三、从模板中解析出文件内容
        List<GeneratedContent> contentList = resolveTemplateContent(genData, mainTemplates, childTemplates);

        // 四、遍历内容，创建文件
        contentList.forEach(s -> FileTool.createFile(s.getFilePath(), s.getFileContent()));
    }

    /**
     * 生成 ZIP
     */
    public void generatorCodeZip(GenTable genTable, ZipOutputStream zip) {

        // 一、组装生成数据
        GenData genData = GenVOBuild.build(genTable);

        // 二、加载模板
        List<GenTemplate> templates = loadTemplateList(genTable.getGenTypeCode());
        // 3.1 过滤出主表模板
        List<GenTemplate> mainTemplates = templates.stream().filter(s -> !s.getChild()).collect(Collectors.toList());
        // 3.2 过滤出子表模板
        List<GenTemplate> childTemplates = templates.stream().filter(GenTemplate::getChild).collect(Collectors.toList());

        // 四、从模板中解析出文件内容
        List<GeneratedContent> contentList = resolveTemplateContent(genData, mainTemplates, childTemplates);

        // 五、将内容加入 ZIP
        for (GeneratedContent content : contentList) {
            StringWriter sw = new StringWriter();
            sw.append(content.getFileContent());
            try {
                zip.putNextEntry(new ZipEntry(content.getFileName()));
                IOUtils.write(sw.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(sw);
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
                throw new CusException(StrUtil.format("（{}）根据模板内容创建ZIP时异常", content.getFileName()));
            }
        }
    }

    /** 加载模板列表 */
    private List<GenTemplate> loadTemplateList(String genType) {
        return LoadTemplateTool.loadTemplateList(GenTypeEnum.getByKey(genType));
    }

    /** 从模板列表中加载文件内容 */
    private List<GeneratedContent> resolveTemplateContent(GenData genData, List<GenTemplate> mainTemplates, List<GenTemplate> childTemplates) {
        String basePath = genConfig.getBasePath();

        // 解析主表模板内容
        List<GeneratedContent> contentList = freeMarkersService.resolveTemplateContent(basePath, genData, mainTemplates);

        // 解析子表模板内容
        genData.getChilds().forEach(child -> contentList.addAll(freeMarkersService.resolveTemplateContent(basePath, child, childTemplates)));

        return contentList;
    }

}
